package com.bwda.dsrs.filecenter.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.bwda.dsrs.base.util.StringUtil;
import com.bwda.dsrs.filecenter.domain.condition.executionpolicy.ExecutionPolicyCondition;
import com.bwda.dsrs.filecenter.domain.po.executionpolicy.ExecutionPolicyPo;
import com.bwda.dsrs.filecenter.domain.po.executionpolicy.TaskDbGroupPo;
import com.bwda.dsrs.filecenter.mapper.dsrs.ExecutionPolicyMapper;
import com.bwda.dsrs.filecenter.service.ExecutionPolicyService;
import com.bwda.dsrs.filecenter.service.ResAuditTaskExecutionService;
import com.bwda.dsrs.filecenter.util.DateTimeUtils;
import com.bwda.dsrs.systemservice.domain.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
 * @author Administrator
 */
@Service
public class ExecutionPolicyServiceImpl extends BaseServiceImpl<ExecutionPolicyPo, ExecutionPolicyCondition, ExecutionPolicyMapper> implements ExecutionPolicyService {
    private static Logger logger = LoggerFactory.getLogger(ExecutionPolicyServiceImpl.class);

    @Resource
    private ExecutionPolicyMapper resAuditTaskCnfgMapper;

    @Resource
    private ResAuditTaskExecutionService resAuditTaskExecutionService;

    @Override
    public void addAuditTask(ExecutionPolicyPo po) {
        //判断任务执行时间  定时执行,每日执行 如果执行时间在当前时间之前则今天不执行将最后一次执行时间设置成当前时间
        // 每周执行 如果当前周是定时任务的周且执行时间在当前时间之前则今天不执行将最后一次执行时间设置成当前时间
        // 每月执行 如果当前月的某一天是定时任务的那天且执行时间在当前时间之前则今天不执行将最后一次执行时间设置成当前时间
        po=checkTaskExecutedTime(po);

        //新增策略任务
        ExecutionPolicyPo executionPolicyPo = insertPo(po);
        //获取ID信息
        Long auditTaskId = executionPolicyPo.getExecutionPolicyId();

        //新增策略任务关联资源范围表
        if (StringUtil.isNotEmpty(po.getRestaskDbGroupPos())) {
            addResAuditTaskResourceScope(po, auditTaskId);
        }

        //如果任务是立即执行
        Long executionCycleTypeId = executionPolicyPo.getExecutionCycleTypeId();
        //任务状态
        Long taskStatus = executionPolicyPo.getTaskStatus();
        if (Constants.ResAuditCycleType.CT_IMMEDIATE.equals(executionCycleTypeId) && Constants.ResAuditTaskStatus.TS_ON.equals(taskStatus)) {
            List<ExecutionPolicyPo> executeTaskList = new ArrayList<>();
            executeTaskList.add(executionPolicyPo);
            resAuditTaskExecutionService.immediateExecute(executeTaskList);
        }


    }

    @Override
    public void setTaskStatus(ExecutionPolicyPo po) {
        //启用停用任务
        this.getMapper().setTaskStatus(po);

    }

    @Override
    public ExecutionPolicyPo queryAuditTaskInfo(Long executionPolicyId) {
        ExecutionPolicyPo po = query(Integer.parseInt(executionPolicyId+""));

        //数据分组
        List<TaskDbGroupPo> resAuditTaskResourcePos = this.getMapper().getTaskDbGroupByTaskId(new Long[]{executionPolicyId});
        if (resAuditTaskResourcePos != null && resAuditTaskResourcePos.size() > 0) {
            po.setTaskDbGroupPos(resAuditTaskResourcePos);
        }
        return po;
    }

    @Override
    public void deleteByIds(Long[] executionPolicyIds) {
        //删除策略任务表
        this.getMapper().deleteByIds(executionPolicyIds);

        //删除策略任务关联资源范围表
        deleteResAuditTaskResourceScope(executionPolicyIds);
    }

    @Override
    public void updateAuditTaskInfo(ExecutionPolicyPo po) {
        //判断任务执行时间  定时执行,每日执行 如果执行时间在当前时间之前则今天不执行将最后一次执行时间设置成当前时间
        // 每周执行 如果当前周是定时任务的周且执行时间在当前时间之前则今天不执行将最后一次执行时间设置成当前时间
        // 每月执行 如果当前月的某一天是定时任务的那天且执行时间在当前时间之前则今天不执行将最后一次执行时间设置成当前时间
        po=checkTaskExecutedTime(po);
        //修改策略任务基础信息
        update(po);

        //策略任务信息修改时设置资源范围
        setTaskResourceScope(po);
    }
    /**
     * 修改策略任务时设置资源范围
     *
     * @param po 任务对象
     */
    @Override
    public void setTaskResourceScope(ExecutionPolicyPo po) {
        Long auditTaskId = po.getExecutionPolicyId();
        //先刪除资源范围
        deleteResAuditTaskResourceScope(new Long[]{auditTaskId});
        //新增策略任务关联资源范围
        addResAuditTaskResourceScope(po, auditTaskId);
    }
    /**
     * 立即执行任务
     *
     * @param taskIds 任务IDS
     */
    @Override
    public void immediateExecuteTask(Long[] taskIds) {
        //查询需要立即执行的任务
        List<ExecutionPolicyPo> poList = this.getMapper().queryResAuditTaskTypeListByTaskId(taskIds);
        resAuditTaskExecutionService.immediateExecute(poList);
    }

    /**
     * 获取所有状态为启用的数据
     * @return
     */
    @Override
    public List<ExecutionPolicyPo> selectResCanRunAuditTaskCnfg() {
        return resAuditTaskCnfgMapper.selectResCanRunAuditTaskCnfg();
    }

    /**
     * 更新最后一次执行时间
     * @param executionPolicyId
     * @param lastExecutionTime
     */
    @Override
    public void updateTaskExecutionTime(Long executionPolicyId, String lastExecutionTime) {
        logger.info("updateTaskExecutionTime, input param auditTaskId:{}, lastExecutionTime:{}", executionPolicyId, lastExecutionTime);
        if (executionPolicyId == null) {
            logger.error("updateTaskExecutionTime, input param auditTaskId is null.");
            return;
        }

        this.getMapper().updateTaskExecutionTime(executionPolicyId, lastExecutionTime);
    }
    /**
     * 根据任务名称查询策略任务数量
     * @param po 策略任务对象
     * @return
     */
    @Override
    public int countResAuditTaskCnfgByTaskName(ExecutionPolicyPo po) {
        return resAuditTaskCnfgMapper.countResAuditTaskCnfgByTaskName(po);
    }

    /**
     * 检测任务执行的时间
     * @param po
     * @return
     */
    private ExecutionPolicyPo checkTaskExecutedTime(ExecutionPolicyPo po) {
        if (po == null || po.getExecutionCycleTypeId() == null) {
            return po;
        }

        //偏移的小时数
        int hourOffset = 0;
        int currDay = DateTimeUtils.getDay(hourOffset);
        logger.info("当前月的currDay:{}",currDay);
        int currWeek = DateTimeUtils.getWeek(hourOffset);
        logger.info("当前周的currWeek:{}",currWeek);
        int currQuarter = DateTimeUtils.getQuarterDay();
        logger.info("当前季度currQuarter:{}",currQuarter);
        String currDate = DateTimeUtils.getDate();
        logger.info("当前时间currDate:{}",currDate);
        String currDateTime = DateTimeUtils.getDateTime();

        if (Constants.ResAuditCycleType.CT_IMMEDIATE.equals(po.getExecutionCycleTypeId())) {
            //立即执行的任务类型，不需要设置
            return po;
        } else if (Constants.ResAuditCycleType.CT_TIMING.equals(po.getExecutionCycleTypeId())) {
            //定时执行的任务类型
            if (DateTimeUtils.compareDateTime(currDateTime, po.getExecutionTime()) == 1) {
                // 如果当前时间大于执行时间则今天不执行将最后一次执行时间设置成当前时间
                po.setLastExecutionTime(DateTimeUtils.getDateTime());
            }
        } else if (Constants.ResAuditCycleType.CT_DAY.equals(po.getExecutionCycleTypeId())) {
            //每天执行的任务类型
            if (DateTimeUtils.compareDateTime(currDateTime, currDate + Constants.STRING_BLANK + po.getExecutionTime()) == 1) {
                // 如果当前时间大于执行时间则今天不执行将最后一次执行时间设置成当前时间
                po.setLastExecutionTime(DateTimeUtils.getDateTime());
            }
        } else if (Constants.ResAuditCycleType.CT_WEEK.equals(po.getExecutionCycleTypeId())) {
            //每周执行的任务类型
            if (currWeek == po.getExecutionDay()
                    && DateTimeUtils.compareDateTime(currDateTime, currDate + Constants.STRING_BLANK + po.getExecutionTime()) == 1) {
                // 如果当前时间大于执行时间则今天不执行将最后一次执行时间设置成当前时间
                po.setLastExecutionTime(DateTimeUtils.getDateTime());
            }
        } else if (Constants.ResAuditCycleType.CT_MONTH.equals(po.getExecutionCycleTypeId())) {
            //每月执行的任务类型
            if (currDay == po.getExecutionDay()
                    && DateTimeUtils.compareDateTime(currDateTime, currDate + Constants.STRING_BLANK + po.getExecutionTime())== 1) {
                // 如果当前月的某一天是定时任务的那天且当前时间大于执行时间则今天不执行将最后一次执行时间设置成当前时间
                po.setLastExecutionTime(DateTimeUtils.getDateTime());
            }
        }else if (Constants.ResAuditCycleType.CT_QUARTER.equals(po.getExecutionCycleTypeId())) {
            //每季度执行的任务类型
            if (currQuarter == po.getExecutionDay()
                    && DateTimeUtils.compareDateTime(currDateTime, currDate + Constants.STRING_BLANK + po.getExecutionTime())== 1) {
                // 如果当前季度的某一天是定时任务的那天且当前时间大于执行时间则今天不执行将最后一次执行时间设置成当前时间
                po.setLastExecutionTime(DateTimeUtils.getDateTime());
            }
        }else if (Constants.ResAuditCycleType.CT_PERIODIC.equals(po.getExecutionCycleTypeId())) {
            if (DateTimeUtils.compareDateTime(currDateTime, currDate + Constants.STRING_BLANK + po.getExecutionTime())== 1){
                // 当前时间大于执行时间则今天不执行将最后一次执行时间设置成当前时间
                po.setLastExecutionTime(DateTimeUtils.getDateTime());
            }
        }
        return po;
    }


    /**
     * 新增策略任务关联资源范围表
     *
     * @param po          任务对象
     * @param auditTaskId 任务ID
     */
    private void addResAuditTaskResourceScope(ExecutionPolicyPo po, Long auditTaskId) {
        List<TaskDbGroupPo> poList = new ArrayList<>();
        //策略任务关联的资源
        List<TaskDbGroupPo> resAuditTaskResourceScopePos = JSON.parseObject(po.getRestaskDbGroupPos(), new TypeReference<ArrayList<TaskDbGroupPo>>(){});
        try {
            if (resAuditTaskResourceScopePos != null && resAuditTaskResourceScopePos.size() > 0) {

                resAuditTaskResourceScopePos.forEach(resAuditTaskResourcePo -> {

                    TaskDbGroupPo taskDbGroupPo = new TaskDbGroupPo();

                    taskDbGroupPo.setExecutionPolicyId(auditTaskId);

                    taskDbGroupPo.setDbGroupTypeId(0L);

                    taskDbGroupPo.setDbGroupId(resAuditTaskResourcePo.getDbGroupId());


                    poList.add(taskDbGroupPo);
                });
            }
            if (poList != null && poList.size() > 0) {
                resAuditTaskCnfgMapper.addBatchResAuditTaskResourceScope(poList);
            }

        } catch (Exception e) {
            logger.error("新增策略任务关联数据组范围时出错了，原因是", e);
        }
    }


    /**
     * 删除策略任务关联资源范围表
     *
     * @param auditTaskIds 任务IDS
     */
    private void deleteResAuditTaskResourceScope(Long[] auditTaskIds) {
       // List<TaskDbGroupPo> resAuditTaskResourceScopePoList = this.getMapper().getTaskDbGroupByTaskId(auditTaskIds);

        this.getMapper().deleteResAuditTaskResourceScope(auditTaskIds);

    }
}